package robot;

//Imports
import arena.Arena;
import arena.Node;
import behavior.Behavior;
import behavior.Util;
import graphics.Point;

/**
 * Super class for VirtualRobot and PhysicalRobot. Defines methods
 * used by both types of robots.
 * @author Gabriel Loewen
 * @author Jimmy Weston
 * @author Jackie O'Quinn
 */
public class Robot {

    /**
     * Defines the robot id
     */
    protected String id;
    /**
     * Robot location in (x,y) format
     */
    protected Point location;
    /**
     * Old robot location in (x,y) format
     */
    protected Point oldLocation;

    protected Point initialLocation;

    public Point getInitialLocation() {
        return initialLocation;
    }
    /**
     * Current robot heading (N,E,S,W)
     */
    public char heading;
    /**
     * Reference to the node that the robot currently occupies, or null
     */
    protected Node node;
    /**
     * The robots currently loaded behavior
     */
    public Behavior behavior;
    /**
     * True if the robot is virtual
     */
    protected boolean virtual;

    /**
     * Constructor, set all required values
     * @param name      The name of the robot
     * @param point     The location of the robot in (X,Y) format
     * @param head      The heading of the robot (N, E, S, W)
     * @param v         True if the robot is virtual, false otherwise
     */
    public Robot(String name, Point point, char head, boolean v) {
        this.id = name;
        this.location = point;
        this.heading = head;
        this.virtual = v;
        this.oldLocation = new Point(point.x,point.y);
        this.initialLocation = new Point(point.x,point.y);
        setLocation(this.location);
    }

    /**
     * Update variables associated with current location and heading
     *
     * @param data      Array of data returned by the behavior
     * @see Util
     */
    public void update(int[] data) {
        if (data[0] != 'X') {
            heading = (char) data[0];
            oldLocation.update(location.x, location.y);
            getArena().nodeMap.get(oldLocation.toString()).isOccupied = false;
            setLocation(new Point(data[1], data[2]));
        }
    }

    /**
     * Return the location of the robot in (x,y) format
     */
    public Point getLocation() {
        return location;
    }

    /**
     * Placeholder for the move method defined in the robot subclasses
     */
    public void move(String goal) {
    }

    /**
     * Sets the location of the robot to a node at location defined by point
     *
     * @param point     The new location in (X,Y) format
     */
    public void setLocation(Point point) {
        this.location = point;
        this.node = getArena().nodeMap.get(point.toString());
        Node.setOccupied(this.node);
    }

    /**
     * Returns the ID of the robot
     */
    public String getID() {
        return this.id;
    }

    /**
     * Returns the heading of the robot
     */
    public char getHeading() {
        return heading;
    }

    /**
     * Sets the heading of the robot
     *
     * @param   head    The new heading of the robot
     */
    public void setHeading(char head) {
        this.heading = head;
    }

    /**
     * Returns a reference to the node that the robot occupies, or null
     */
    public Node getNode() {
        return this.node;
    }

    /**
     * Returns the appropriate arena object for this robot.
     * Either virtual or physical.
     */
    public Arena getArena() {
        if (virtual)
            return criep.CRIEP.VirtualArena;
        else
            return criep.CRIEP.PhysicalArena;
    }

    public char[][] getPositionMatrix(){
        char[][] matrix = new char[getArena().height][getArena().width];
        for(int i = 0; i < matrix.length; i++){
            for(int j = 0; j < matrix[i].length; j++){
                matrix[i][j] = '-';
            }
        }

        for(int i = 0; i < getArena().robotMap.size(); i++){
            matrix[getArena().robotMap.get("Robot" + (i + 1)).getLocation().y][getArena().robotMap.get("Robot" + (i + 1)).getLocation().x] = Character.forDigit(i + 1, 10);
        }


        return matrix;
    }

    public void printPositionMatrix(char[][] matrix){

        for(int i = 0; i < matrix.length; i++){
            for(int j = 0; j < matrix[i].length; j++){
                System.out.print(" " + matrix[i][j]);
            }
            System.out.print("\n");
        }
        System.out.print("\n");
    }

}
